#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <math.h>


/*-------------------------------------------定义参数部分------------------------------------------*/

#define TABLE_SIZE 10 //哈希表一共有十个位置，每个位置会存储一个多项式
#define BUCKET_SIZE 10 //每个桶里面至多有十个元素可以存储
#define USER_NUMBER 5 //定义目前云平台可以供五个用户使用
#define W_NUM 3 //定义随机多项式的最高次项为3

/*-------------------------------------------定义参数部分------------------------------------------*/

/*-------------------------------------------多项式结构部分------------------------------------------*/

typedef struct {
    int randomId; //随机数标识
    int Pmax; //多项式的最高次项
    long long Px_coef[BUCKET_SIZE + 1]; //构造一个元素数量为11的多项式，这里存储每一项的系数
} P_x; //构建函数P(x)

typedef struct {
    int randomId; //每个root也会对应随机数标识
    int root[BUCKET_SIZE]; //每个P(x)的初始随机数
} roots; //构建每个桶中的随机数根（e1，e2...e10）

typedef struct {
    int randomId; //随机数标识
    int omax; //多项式中最高次项的幂数
    long long ox_coef[BUCKET_SIZE + 1]; //o函数里的多项式，五个元素，从最高次项x^10一直到x^6
} o_x; //创建一个o(x)多项式的结构

typedef struct {
    int randomId; //随机数标识
    int zmax; //多项式中最高次项的幂数，此处为5
    long long zx_coef[BUCKET_SIZE + 1]; //z函数中的多项式，六个元素，从最高次项x^5一直到常数
} z_x; //创建一个z(x)的多项式结构

typedef struct {
    int randomId;
    int wx_coef[W_NUM + 1]; //一个最高次为3的随机多项式
} w_x;

typedef struct {
    int randomId;
    long long qx_coef[BUCKET_SIZE + W_NUM + 1];
} q_x; //这是被委托用户用来计算求交时需要的多项式

typedef struct {
    int randomId;
    long long tx_coef[BUCKET_SIZE + W_NUM + 1];
} t_x;

typedef struct {
    long long rie_x_coef[BUCKET_SIZE + W_NUM + 1];
} rie_x;


/*-------------------------------------------多项式结构部分------------------------------------------*/

/*-------------------------------------------表格结构部分------------------------------------------*/

typedef struct {
    P_x *HT[TABLE_SIZE];
} HashTable; //创建一个哈希表，每个表项对应一个桶，桶中是多项式，这个是做初始化用的。

typedef struct {
    o_x *ox[TABLE_SIZE];
} o_table; //中间态，用来临时计算

typedef struct {
    z_x *ztable[TABLE_SIZE];
} z_table; //用户自己保有

typedef struct {
    o_x *ohat[TABLE_SIZE];
} o_hat_table; //发送给云平台的混淆后的哈希表

typedef struct {
    roots *r_table[TABLE_SIZE];
} roots_table; //每个用户都自己持有一个多项式初始化随机数根的表格

typedef struct {
    int num[TABLE_SIZE]; //记录一下每个桶里面目前有多少个元素。
} num_table;

typedef struct //被委托用户生成的随机掩码多项式
{
    w_x *wx_table[2][TABLE_SIZE];
} w_table;

typedef struct {
    z_x *z_secret_table[2][TABLE_SIZE];
} z_secret; //用户生成自己z(x)函数的秘密分享值

typedef struct {
    q_x *my_qtable[TABLE_SIZE];
    q_x *other_qtable[TABLE_SIZE];
    q_x *final_qtable[TABLE_SIZE];
} q_table; //生成求交的RIE表格

typedef struct {
    t_x *User_A_t_table[TABLE_SIZE];
    t_x *User_B_t_table[TABLE_SIZE];
    t_x *final_t_table[TABLE_SIZE];
} t_table;

typedef struct {
    rie_x *my_rie_table[TABLE_SIZE];
} rie_table;


/*-------------------------------------------表格结构部分------------------------------------------*/

/*-------------------------------------------角色结构部分------------------------------------------*/
typedef struct {
    char name[50]; //用户的名称
    int User_symbol; //用户的标识符
    P_x *Px; //用于临时生成可用于计算的多项式
    HashTable *my_Hashtable; //用户自己手里的哈希表
    z_table *my_z_table; //用户自己持有的多项式部分表
    z_x *other_zx[TABLE_SIZE]; //从其他用户处得到的秘密分享的z_x
    z_secret *secret_share_table; //用户生成自己z(x)函数的秘密分享值
    o_table *my_o_table; //用户准备发给云平台的，没有混淆的o(x)表
    roots_table *my_root_table; //用户生成哈希表的时候存储的根的表
    num_table *my_num_table; //用户存储在每个桶中有多少个元素
    o_hat_table *my_o_hat_table; // 用户发送给云平台的已经混淆的o_hat(x)表
    int label[TABLE_SIZE]; //用户的随机标识表
    int label_hat[TABLE_SIZE]; //混淆后的用户随机标识表
    int temp_label[TABLE_SIZE]; //用于接受其他用户发过来的随机标识表
    int label_matrix[2][TABLE_SIZE]; //用于生成标签对应矩阵;
    w_table *my_w_table; //用于存储求交时生成的随机多项式
    q_table *qtable; //用于存储求交时生成的RIE多项式
    rie_table *my_rie_table; //接收委托用户和云平台发送的隐私求交信息
    int shuffle_lable_matrix[2][TABLE_SIZE]; //这个结构负责记录，混淆完后的排列顺序与原始顺序之间的关联
} User; //用户角色定义

typedef struct {
    int User_symbol[USER_NUMBER]; //目前云平台服务器可以服务5个用户
    o_hat_table *user_o_hat_table[USER_NUMBER]; //每个用户可以有自己的一个o_hat表
    z_table *user_z_table[USER_NUMBER]; //用于在判断交集时使用
    long long temp_result[TABLE_SIZE][BUCKET_SIZE + 1]; //用于暂时存放ohat和z的加和
    int label_hat[USER_NUMBER][TABLE_SIZE]; //用于接收用户发来的L-hat
    w_table *cloud_w_table; // 用于接收用户生成的求交时随机多项式
    t_table *cloud_t_table; //用于生成t向量，隐私求交用
} CloudServer; //云平台角色定义

/*-------------------------------------------结构部分------------------------------------------*/

/*-------------------------------------------函数初始化部分------------------------------------------*/

int Hash(int s) {
    //一个简单的哈希函数，每个待输入的元素先哈希，然后决定放到哪个桶里。
    int hash = s % 10;
    return hash;
}

void generate_randomid(User *u) //初始化随机标识符
{
    for (size_t i = 0; i < TABLE_SIZE; i++) {
        u->my_Hashtable->HT[i]->randomId = rand() % 1000; //获得每个哈希桶对应的随机标识
        u->my_o_table->ox[i]->randomId = u->my_Hashtable->HT[i]->randomId; //将随机标识传递到o(x)表中
        u->my_root_table->r_table[i]->randomId = u->my_Hashtable->HT[i]->randomId; // 将随机标识传递到root 表中
        u->my_z_table->ztable[i]->randomId = u->my_Hashtable->HT[i]->randomId; // 将随机标识传递到z(x)表中
        u->my_o_hat_table->ohat[i]->randomId = u->my_Hashtable->HT[i]->randomId; // 将随机标识传递到o_hat(x)表中
        u->label[i] = u->my_Hashtable->HT[i]->randomId; //将随机标识传递到label表里
        u->label_hat[i] = u->my_Hashtable->HT[i]->randomId; //将随机标识传到o_hat 的随机标识表里
    }
}


void generate_roots(User *u) //生成每个用户的随机数表
{
    for (size_t i = 0; i < TABLE_SIZE; i++) // 对表进行循环
    {
        for (size_t j = 0; j < BUCKET_SIZE; j++) // 对表中每个位置进行循环
        {
            u->my_root_table->r_table[i]->root[j] = (rand() % 5 ) + 1;
        }
    }
}

void generate_polynomial(User *u) {
    // 初始化多项式系数数组，系数初始为0
    long long coefficients[BUCKET_SIZE+1];
    coefficients[0] = 1;
    for (int i = 1; i <= BUCKET_SIZE; i++) {
        coefficients[i] = 0;
    }

    // 使用多项式展开公式进行逐步展开
    for (size_t j = 0; j < TABLE_SIZE; j++) {
        coefficients[0] = 1;
        for (int i = 1; i <= BUCKET_SIZE; i++) {
            coefficients[i] = 0;
        }
        for (int i = 0; i < BUCKET_SIZE; i++) {
            //每个桶的P（x），把根调用进去
            int root = u->my_root_table->r_table[j]->root[i];

            // 从高次项开始更新系数，使用展开公式
            for (int k = i; k >= 0; k--) {
                coefficients[k + 1] += coefficients[k];
                coefficients[k] *= -root;
            }
        }

        for (size_t o = 0; o < BUCKET_SIZE + 1; o++) {
            u->my_Hashtable->HT[j]->Px_coef[o] = coefficients[o]; // 构造哈希表
        }
        u->my_num_table->num[j] = 0; //在这里一同先进行计数的初始化。
    }
}

void generate_divide_polynomial(User *u) {
    // 将P(x)分割为o(x)和z(x) (初始化阶段)

    for (size_t i = 0; i < TABLE_SIZE; i++) // 完成o(x)和z(x)表的构建
    {
        // 将随机系数发送给o(x)和o_hat(x)
        for (int j = 0; j < BUCKET_SIZE + 1; j++) {
            u->my_o_table->ox[i]->ox_coef[j] = rand();
            u->my_o_hat_table->ohat[i]->ox_coef[j] = u->my_o_table->ox[i]->ox_coef[j];
        }

        // 将另一部分发送给z(x)
        for (int j = 0; j < BUCKET_SIZE + 1; j++) {
            u->my_z_table->ztable[i]->zx_coef[j] =
                    u->my_Hashtable->HT[i]->Px_coef[j] - u->my_o_table->ox[i]->ox_coef[j];
        }
    }
}


// 用 Fisher-Yates 洗牌算法混淆多项式的存储顺序
void shufflePolynomials(User *u) {
    //把o(x)的顺序传输过来，混淆后传输成o_hat(x)
    long long temp[BUCKET_SIZE + 1];
    int temp_randomId;
    int temp_number = 0;

    for (int i = TABLE_SIZE-1; i > 0; i--) {
        int j = rand() % (i + 1);
        //更新一下每个桶对应的随机标识
        temp_randomId = u->my_o_hat_table->ohat[i]->randomId; //把第i个桶的随机标识先保留起来
        u->my_o_hat_table->ohat[i]->randomId = u->my_o_hat_table->ohat[j]->randomId; //将第j个桶的随机标识放到第i个桶中
        u->label_hat[i] = u->label_hat[j]; //用户ohat表的第i个随机标识换成第j个随机标识
        u->my_o_hat_table->ohat[j]->randomId = temp_randomId; //将第i个桶的随机标识放入第j个桶中
        u->label_hat[j] = temp_randomId; //用户ohat表的第j个随机标识换成第i个随机标识

        temp_number = u->shuffle_lable_matrix[1][i];
        u->shuffle_lable_matrix[1][i] = u->shuffle_lable_matrix[1][j];
        u->shuffle_lable_matrix[1][j] = temp_number;

        for (size_t k = 0; k < BUCKET_SIZE + 1; k++) {
            temp[k] = u->my_o_hat_table->ohat[i]->ox_coef[k];
            u->my_o_hat_table->ohat[i]->ox_coef[k] = u->my_o_hat_table->ohat[j]->ox_coef[k];
            u->my_o_hat_table->ohat[j]->ox_coef[k] = temp[k];
        }
    }
}

void send_o_hat_table_ToCloud(CloudServer *c, User *u) {
    //将o_hat表发送给云服务器
    for (int i = 0; i < TABLE_SIZE; i++) {
        for (int j = 0; j < BUCKET_SIZE + 1; j++) {
            c->user_o_hat_table[u->User_symbol]->ohat[i]->ox_coef[j] = u->my_o_hat_table->ohat[i]->ox_coef[j];
        }
        c->user_o_hat_table[u->User_symbol]->ohat[i]->randomId = u->my_o_hat_table->ohat[i]->randomId;
    }
}


// 完整的 `initialize_user` 函数
void initialize_user(User *u) {
    u->my_Hashtable = malloc(sizeof(HashTable));
    u->my_z_table = malloc(sizeof(z_table));
    u->my_o_table = malloc(sizeof(o_table));
    u->my_root_table = malloc(sizeof(roots_table));
    u->my_num_table = malloc(sizeof(num_table));
    u->my_o_hat_table = malloc(sizeof(o_hat_table));
    u->Px = malloc(sizeof(P_x));
    u->secret_share_table = malloc(sizeof(z_secret));
    u->my_w_table = malloc(sizeof(w_table));
    u->qtable = malloc(sizeof(q_table)); // 分配内存
    u->my_rie_table = malloc(sizeof(rie_table));

    // 初始化 qtable 中的元素为 0
    for (size_t i = 0; i < TABLE_SIZE; i++) {
        u->qtable->my_qtable[i] = malloc(sizeof(q_x));
        u->qtable->other_qtable[i] = malloc(sizeof(q_x));
        u->qtable->final_qtable[i] = malloc(sizeof(q_x));

        // 将每个 q_x 结构体的所有字段设置为 0
        memset(u->qtable->my_qtable[i], 0, sizeof(q_x));
        memset(u->qtable->other_qtable[i], 0, sizeof(q_x));
        memset(u->qtable->final_qtable[i], 0, sizeof(q_x));
    }

    // 其他初始化代码
    for (size_t i = 0; i < TABLE_SIZE; i++) {
        u->shuffle_lable_matrix[0][i] = i;
        u->shuffle_lable_matrix[1][i] = i;
    }

    for (int i = 0; i < TABLE_SIZE; i++) {
        u->my_Hashtable->HT[i] = malloc(sizeof(P_x));
        u->my_z_table->ztable[i] = malloc(sizeof(z_x));
        u->my_o_table->ox[i] = malloc(sizeof(o_x));
        u->my_root_table->r_table[i] = malloc(sizeof(roots));
        u->my_o_hat_table->ohat[i] = malloc(sizeof(o_x));
        u->my_rie_table->my_rie_table[i] = malloc(sizeof(rie_x));
        // u->qtable->my_qtable[i] = malloc(sizeof(q_x));
        // u->qtable->other_qtable[i] = malloc(sizeof(q_x));
        // u->qtable->final_qtable[i] = malloc(sizeof(q_x));
        u->other_zx[i] = malloc(sizeof(z_x));
        if (u->other_zx[i] == NULL) {
            fprintf(stderr, "Memory allocation failed for other_zx[%d]\n", i);
            exit(1);
        }
        for (int j = 0; j < 2; j++) {
            u->my_w_table->wx_table[j][i] = malloc(sizeof(w_x));
            u->secret_share_table->z_secret_table[j][i] = malloc(sizeof(z_x));
        }
    }
}


// 完整的 `initialize_cloud` 函数
void initialize_cloud(CloudServer *c) {
    c->cloud_w_table = malloc(sizeof(w_table));
    c->cloud_t_table = malloc(sizeof(t_table));

    // 初始化 cloud_t_table 中的元素为 0
    for (int i = 0; i < TABLE_SIZE; i++) {
        c->cloud_t_table->User_A_t_table[i] = malloc(sizeof(t_x));
        c->cloud_t_table->User_B_t_table[i] = malloc(sizeof(t_x));
        c->cloud_t_table->final_t_table[i] = malloc(sizeof(t_x));

        // 将每个 t_x 结构体的所有字段设置为 0
        memset(c->cloud_t_table->User_A_t_table[i], 0, sizeof(t_x));
        memset(c->cloud_t_table->User_B_t_table[i], 0, sizeof(t_x));
        memset(c->cloud_t_table->final_t_table[i], 0, sizeof(t_x));
    }

    for (int i = 0; i < USER_NUMBER; i++) {
        c->user_o_hat_table[i] = malloc(sizeof(o_hat_table));
        c->user_z_table[i] = malloc(sizeof(z_table));

        for (int j = 0; j < TABLE_SIZE; j++) {
            c->user_o_hat_table[i]->ohat[j] = malloc(sizeof(o_x));
            c->user_z_table[i]->ztable[j] = malloc(sizeof(z_x));
        }
    }

    for (int i = 0; i < TABLE_SIZE; i++) {
        c->cloud_t_table->User_A_t_table[i] = malloc(sizeof(t_x));
        c->cloud_t_table->User_B_t_table[i] = malloc(sizeof(t_x));
        c->cloud_t_table->final_t_table[i] = malloc(sizeof(t_x));

        // 将每个 t_x 结构体的所有字段设置为 0
        memset(c->cloud_t_table->User_A_t_table[i], 0, sizeof(t_x));
        memset(c->cloud_t_table->User_B_t_table[i], 0, sizeof(t_x));
        memset(c->cloud_t_table->final_t_table[i], 0, sizeof(t_x));

        for (int j = 0; j < 2; j++) {
            c->cloud_w_table->wx_table[j][i] = malloc(sizeof(w_x));
        }
    }
}


void free_user(User *u) {
    if (u == NULL) return;

    // 释放 my_Hashtable 中的每个 P_x 指针
    for (int i = 0; i < TABLE_SIZE; i++) {
        free(u->my_Hashtable->HT[i]);
    }
    free(u->my_Hashtable);

    // 释放 my_z_table 中的每个 z_x 指针
    for (int i = 0; i < TABLE_SIZE; i++) {
        free(u->my_z_table->ztable[i]);
    }
    free(u->my_z_table);

    // 释放 my_o_table 中的每个 o_x 指针
    for (int i = 0; i < TABLE_SIZE; i++) {
        free(u->my_o_table->ox[i]);
    }
    free(u->my_o_table);

    // 释放 my_root_table 中的每个 roots 指针
    for (int i = 0; i < TABLE_SIZE; i++) {
        free(u->my_root_table->r_table[i]);
    }
    free(u->my_root_table);

    // 释放 my_o_hat_table 中的每个 o_x 指针
    for (int i = 0; i < TABLE_SIZE; i++) {
        free(u->my_o_hat_table->ohat[i]);
    }
    free(u->my_o_hat_table);

    // 释放 my_rie_table 中的每个 rie_x 指针
    for (int i = 0; i < TABLE_SIZE; i++) {
        free(u->my_rie_table->my_rie_table[i]);
    }
    free(u->my_rie_table);

    // 释放 q_table 中的多项式指针
    for (int i = 0; i < TABLE_SIZE; i++) {
        free(u->qtable->my_qtable[i]);
        free(u->qtable->other_qtable[i]);
        free(u->qtable->final_qtable[i]);
    }
    free(u->qtable);

    // 释放 w_table 和 secret_share_table 中的二维数组
    for (int i = 0; i < TABLE_SIZE; i++) {
        for (int j = 0; j < 2; j++) {
            free(u->my_w_table->wx_table[j][i]);
            free(u->secret_share_table->z_secret_table[j][i]);
        }
    }
    free(u->my_w_table);
    free(u->secret_share_table);

    // 释放 Px 指针
    free(u->Px);

    // 释放 num_table
    free(u->my_num_table);
}


void free_cloud(CloudServer *c) {
    if (c == NULL) return;

    // 释放 user_o_hat_table 和 user_z_table 中的每个表
    for (int i = 0; i < USER_NUMBER; i++) {
        for (int j = 0; j < TABLE_SIZE; j++) {
            free(c->user_o_hat_table[i]->ohat[j]);
            free(c->user_z_table[i]->ztable[j]);
        }
        free(c->user_o_hat_table[i]);
        free(c->user_z_table[i]);
    }

    // 释放 cloud_w_table 中的二维数组
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < TABLE_SIZE; j++) {
            free(c->cloud_w_table->wx_table[i][j]);
        }
    }
    free(c->cloud_w_table);

    // 释放 cloud_t_table 中的 t_x 指针
    for (int i = 0; i < TABLE_SIZE; i++) {
        free(c->cloud_t_table->User_A_t_table[i]);
        free(c->cloud_t_table->User_B_t_table[i]);
        free(c->cloud_t_table->final_t_table[i]);
    }
    free(c->cloud_t_table);
}


/*-------------------------------------------函数初始化部分------------------------------------------*/

/*-------------------------------------------临时应用函数部分------------------------------------------*/

// 从云服务器获取对应的 o_hat(x)，和自己的z(x)结合以后，变成一个临时的P(x)
void getFromCloud(CloudServer *c, User *u, int randomId, int hashnum) {
    for (int i = 0; i < TABLE_SIZE; i++) {
        if (c->user_o_hat_table[u->User_symbol]->ohat[i]->randomId == randomId) {
            for (int j = 0; j < BUCKET_SIZE + 1; j++) {
                u->Px->Px_coef[j] = c->user_o_hat_table[u->User_symbol]->ohat[i]->ox_coef[j] + u->my_z_table->ztable[
                                        hashnum]->zx_coef[j]; //将o_hat（x）中的元素发送给临时P(x)
            }
            u->Px->randomId = u->my_z_table->ztable[hashnum]->randomId;
            break;
        }
    }
}

void divide_and_send_polynomial(CloudServer *c, User *u, int hashnum) {
    //将P(x)秘密分享为两部分，并返回给云平台

    for (size_t j = 0; j < TABLE_SIZE; j++) //找到该用户要更新哪个桶
    {
        if (c->user_o_hat_table[u->User_symbol]->ohat[j]->randomId == u->Px->randomId) //找到对应的桶
        {
            for (size_t k = 0; k < BUCKET_SIZE + 1; k++) {
                c->user_o_hat_table[u->User_symbol]->ohat[j]->ox_coef[k] = rand();
                u->my_z_table->ztable[hashnum]->zx_coef[k] =
                        u->Px->Px_coef[k] - c->user_o_hat_table[u->User_symbol]->ohat[j]->ox_coef[k];
            }
        }
    }
}


void check() {
    printf("插入操作执行中，插入完成后的云平台存储的ohat多项式为\n");

    for (size_t i = 0; i < BUCKET_SIZE+1; i++) //检查一下运行效果
    {
        printf(" x^%d + ", i);
    }
    printf("\n");

    for (size_t i = 0; i < BUCKET_SIZE+1; i++) //检查一下运行效果
    {
        printf(" x^%d + ", i);
    }
    printf("\n");
}

long long power(long long x, int n) {//求幂函数
    long long result = 1;

    // 快速幂计算
    while (n > 0) {
        if (n % 2 == 1) {  // 如果 n 是奇数
            result *= x;
        }
        x *= x;  // 将底数平方
        n /= 2;  // 指数减半
    }

    return result;
}

/*-------------------------------------------临时应用函数部分------------------------------------------*/

/*-------------------------------------------操作实现函数部分------------------------------------------*/

void generate(User *u, CloudServer *c) {
    //初始化一个用户

    generate_roots(u);//给用户生成随机数根
    generate_randomid(u); //给用户生成随机标识
    generate_polynomial(u); //用户初始化哈希表
    generate_divide_polynomial(u); //将初始化后的哈希表分为两部分
    shufflePolynomials(u); //混淆生成的o(x)表
    send_o_hat_table_ToCloud(c, u); //将混淆后的表发送给云平台
}

void insert(User *u, CloudServer *c, int s) {
    //用户插入数据函数
    memset(u->Px->Px_coef, 0, sizeof(u->Px->Px_coef));
    int hash_number = Hash(s); //先找到这个元素要放到哪个位置
    int root_num = u->my_num_table->num[hash_number]; //这个桶里需要被除掉的随机数根
    int root = u->my_root_table->r_table[hash_number]->root[root_num];

    
    getFromCloud(c, u, u->my_Hashtable->HT[hash_number]->randomId, hash_number);

    

    /*----------------- 多项式除法---------------*/

    long long result[BUCKET_SIZE + 1] = {0};
    long long temp_p[BUCKET_SIZE] = {0};
    temp_p[BUCKET_SIZE-1] = u->Px->Px_coef[BUCKET_SIZE]; //设置最高次项
    for (size_t i = BUCKET_SIZE-1; i > 0; i--) {
        temp_p[i - 1] = u->Px->Px_coef[i] + root * temp_p[i];
    }

    /*----------------- 多项式除法---------------*/

    

    /*----------------- 多项式乘法---------------*/
    // 对每一项执行乘法
    for (int i = BUCKET_SIZE-1; i >= 0; i--) {
        result[i + 1] += temp_p[i];
        result[i] -= temp_p[i] * (s);
    }
    for (size_t i = 0; i < BUCKET_SIZE + 1; i++) {
        u->Px->Px_coef[i] = result[i];
    }
    /*----------------- 多项式乘法---------------*/

    

    divide_and_send_polynomial(c, u, hash_number); //将插入完成后的新桶分发给用户和云平台。

    u->my_num_table->num[hash_number] += 1; // 更新一下桶里面元素的数量。
}


void delete(User *u, CloudServer *c, int s) {
    //用户删除数据函数
    memset(u->Px->Px_coef, 0, sizeof(u->Px->Px_coef));
    int hash_number = Hash(s); //先找到这个被删除的元素在表中哪个位置
    int root_num = u->my_num_table->num[hash_number]; //这个桶里需要被恢复的随机数根

    getFromCloud(c, u, u->my_Hashtable->HT[hash_number]->randomId, hash_number);

   

    /*----------------- 多项式除法---------------*/
    long long temp_p[10] = {0};
    long long result[11] = {0};
    int root_value = (rand() % 5) + 1; //产生一个新的随机数
    u->my_root_table->r_table[hash_number]->root[u->my_num_table->num[hash_number]] = root_value; //将该随机数填充到随机数根表当中

    temp_p[9] = u->Px->Px_coef[10]; //设置最高次项
    for (size_t i = 9; i > 0; i--) {
        temp_p[i - 1] = u->Px->Px_coef[i] + s * temp_p[i];
    }

    

    /*----------------- 多项式除法---------------*/

    /*printf("删除操作执行中，被除后的多项式为\n");
    for (size_t i = 0; i < 10; i++) //检查一下运行效果，这里是除法阶段
    {
        printf("%d x^%d + ", temp_p[i], i);
    }
    printf("\n");

    /*----------------- 多项式乘法---------------*/
    // 对每一项执行乘法*/

    for (int i = 9; i >= 0; i--) {
        result[i + 1] += temp_p[i];
        result[i] -= temp_p[i] * (root_value);
    }
    for (size_t i = 0; i < BUCKET_SIZE + 1; i++) {
        u->Px->Px_coef[i] = result[i];
    }

    /*----------------- 多项式乘法---------------*/


    divide_and_send_polynomial(c, u, hash_number); //将插入完成后的新桶分发给用户和云平台。
    for (size_t i = 0; i < TABLE_SIZE + 1; i++) {
        u->Px->Px_coef[i] = 0;
    }
    u->my_num_table->num[hash_number] -= 1; // 更新一下桶里面元素的数量。
}


void RIE(User *A, User *B, CloudServer *C) {
    //这个函数就是两个用户之间查看是否存在元素交集

    //我们让用户A扮演真正实施查找操作的角色,让用户B扮演委托查找的角色

    /*---------------------------------初始化过程------------------------------------------*/

    for (size_t i = 0; i < TABLE_SIZE; i++) //委托用户A随机生成两个随机多项式
    {
        for (size_t j = 0; j < W_NUM + 1; j++) {
            A->my_w_table->wx_table[0][i]->wx_coef[j] = (rand() % 5) + 1; //给A的随机多项式赋值
            A->my_w_table->wx_table[1][i]->wx_coef[j] = (rand() % 5) + 1; //给B的随机多项式赋值
        }
    }


    for (size_t i = 0; i < TABLE_SIZE; i++) {
        //用户B自己生成Z_B_0和Z_B_1
        for (size_t j = 0; j < BUCKET_SIZE + 1; j++) {
            B->secret_share_table->z_secret_table[0][i]->zx_coef[j] =  rand()% 10000;
            B->secret_share_table->z_secret_table[1][i]->zx_coef[j] = B->my_z_table->ztable[i]->zx_coef[j] - B->secret_share_table->z_secret_table[0][i]->zx_coef[j];
        }
        B->secret_share_table->z_secret_table[0][i]->randomId = B->my_z_table->ztable[i]->randomId;
        B->secret_share_table->z_secret_table[1][i]->randomId = B->my_z_table->ztable[i]->randomId;
    }

    for (size_t i = 0; i < TABLE_SIZE; i++) //委托用户A生成两个用户的随机标识矩阵
    {
        A->label_matrix[0][i] = A->my_z_table->ztable[i]->randomId;
        A->label_matrix[1][i] = B->my_z_table->ztable[i]->randomId;
    }

    /*---------------------------------初始化过程------------------------------------------*/

    /*-----------------------将Z_B_0发送给云平台C的过程----------------------------*/

    for (size_t j = 0; j < TABLE_SIZE; j++) //云平台中C找对应的桶 j
    {
        for (size_t k = 0; k < TABLE_SIZE; k++) //用户B找对应的桶 k
        {
            if (C->user_o_hat_table[B->User_symbol]->ohat[j]->randomId == B->my_z_table->ztable[k]->randomId)
            //查看随机标识是否对应
            {
                for (size_t i = 0; i < BUCKET_SIZE + 1; i++) //将云平台对应的桶中填充为用户的秘密分享信息
                {
                    C->user_z_table[B->User_symbol]->ztable[j]->zx_coef[i] = B->secret_share_table->z_secret_table[0][k]->zx_coef[i];
                }
                C->user_z_table[B->User_symbol]->ztable[j]->randomId = B->secret_share_table->z_secret_table[0][k]->randomId; //将随机标识也赋值过去
            }
        }
    } //注意，在这里，z_B_0和ohat_B的排列顺序是一样的

    /*-----------------------将Z_B_0发送给云平台C的过程----------------------------*/

    /*-----------------------将Z_B_1发送给用户A的过程------------------------------*/

    for (size_t i = 0; i < TABLE_SIZE; i++) {
        A->other_zx[i]->randomId = B->secret_share_table->z_secret_table[1][i]->randomId;
        for (size_t j = 0; j < BUCKET_SIZE + 1; j++) {
            A->other_zx[i]->zx_coef[j] = B->secret_share_table->z_secret_table[1][i]->zx_coef[j];
        }
    }
    //这里Z_B_1的排列顺序就是原始排列

    /*-----------------------将Z_B_1发送给用户A的过程------------------------------*/

    /*-----------------------用户A计算RIE随机编码------------------------------*/


    for (size_t i = 0; i < TABLE_SIZE; i++) // 计算zA(x)的RIE掩码部分
    {
        A->qtable->my_qtable[i]->randomId = A->my_z_table->ztable[i]->randomId; //全部使用用户A的随机标识作为认证
        for (size_t j = 0; j <= BUCKET_SIZE; j++) {
            for (size_t k = 0; k <= W_NUM; k++) {
                A->qtable->my_qtable[i]->qx_coef[j + k] += A->my_z_table->ztable[i]->zx_coef[j] * A->my_w_table->wx_table[0][i]->wx_coef[k];
            }
        }
    }

    for (size_t i = 0; i < TABLE_SIZE; i++) // 计算zB(x)_1的RIE掩码部分
    {
        for (size_t j = 0; j <= BUCKET_SIZE; j++) {
            for (size_t k = 0; k <= W_NUM; k++) {
                A->qtable->other_qtable[i]->qx_coef[j + k] += A->other_zx[i]->zx_coef[j] * A->my_w_table->wx_table[1][i]->wx_coef[k];
            }
        }
    }

    for (size_t i = 0; i < TABLE_SIZE; i++) //将上面计算的两部分进行合并
    {
        A->qtable->final_qtable[i]->randomId = A->qtable->my_qtable[i]->randomId;
        for (size_t j = 0; j <= BUCKET_SIZE + W_NUM; j++) {
            A->qtable->final_qtable[i]->qx_coef[j] =
                    A->qtable->my_qtable[i]->qx_coef[j] + A->qtable->other_qtable[i]->qx_coef[j];
        }
    }
    //这里计算完以后，就是原始排列顺序

    /*-----------------------用户A计算RIE随机编码------------------------------*/

    /*-----------------------用户A向云平台发送RIE过程中用到的随机多项式------------------------------*/


    for (size_t i = 0; i < TABLE_SIZE; i++) //对C中的表格进行遍历搜寻
    {
        for (size_t j = 0; j < TABLE_SIZE; j++) //对用户A中的表格进行遍历搜寻
        {
            if (C->user_o_hat_table[A->User_symbol]->ohat[i]->randomId == A->label_matrix[0][j]) {
                for (size_t k = 0; k < W_NUM + 1; k++) {
                    C->cloud_w_table->wx_table[0][i]->wx_coef[k] = A->my_w_table->wx_table[0][j]->wx_coef[k];
                }
            }
        }

        for (size_t j = 0; j < TABLE_SIZE; j++) //对用户B中的表格进行遍历搜寻
        {
            if (C->user_o_hat_table[B->User_symbol]->ohat[i]->randomId == A->label_matrix[1][j]) {
                for (size_t k = 0; k < W_NUM + 1; k++) {
                    C->cloud_w_table->wx_table[1][i]->wx_coef[k] = A->my_w_table->wx_table[1][j]->wx_coef[k];
                }
            }
        }
    }

    /*-----------------------用户A向云平台发送RIE过程中用到的随机多项式------------------------------*/

    /*-----------------------云平台计算RIE随机编码------------------------------*/

    for (size_t i = 0; i < TABLE_SIZE; i++) //把用户B传输过来的z_B_0和在云平台存储的ohat_B加和到一起
    {
        for (size_t j = 0; j < BUCKET_SIZE + 1; j++) {
            C->temp_result[i][j] = C->user_o_hat_table[B->User_symbol]->ohat[i]->ox_coef[j] + C->user_z_table[B->User_symbol]->ztable[i]->zx_coef[j];
        }
    }//现在是B 的 ohat的顺序

    for (size_t i = 0; i < TABLE_SIZE; i++) //先用w_A对A的ohat进行掩码操作，计算A的t值
    {
        C->cloud_t_table->User_A_t_table[i]->randomId = C->user_o_hat_table[A->User_symbol]->ohat[i]->randomId;
        //全部使用用户A的随机标识作为认证
        for (size_t j = 0; j <= BUCKET_SIZE; j++) {
            for (size_t k = 0; k <= W_NUM; k++) {
                C->cloud_t_table->User_A_t_table[i]->tx_coef[j + k] += C->user_o_hat_table[A->User_symbol]->ohat[i]->ox_coef[j] * C->cloud_w_table->wx_table[0][i]->wx_coef[k];
            }
        }
    }//这里现在是A的ohat 顺序

    for (size_t i = 0; i < TABLE_SIZE; i++) //云平台计算用户B的t值
    {
        C->cloud_t_table->User_B_t_table[i]->randomId = C->user_o_hat_table[B->User_symbol]->ohat[i]->randomId;
        //将随机标识传递过去
        for (size_t j = 0; j <= BUCKET_SIZE; j++) {
            for (size_t k = 0; k <= W_NUM; k++) {
                C->cloud_t_table->User_B_t_table[i]->tx_coef[j + k] += C->temp_result[i][j] * C->cloud_w_table->wx_table[1][i]->wx_coef[k]; //用刚刚计算的结果进行计算
            }
        }
    }

    for (size_t i = 0; i < TABLE_SIZE; i++) //对用户A的随机标识进行查找
    {
        for (size_t j = 0; j < TABLE_SIZE; j++) //对用户B的随机标识进行查找
        {
            for (size_t k = 0; k < TABLE_SIZE; k++) //在A用户生成的标识矩阵中进行比对
            {
                if (C->cloud_t_table->User_A_t_table[i]->randomId == A->label_matrix[0][k] && C->cloud_t_table->
                    User_B_t_table[j]->randomId == A->label_matrix[1][k]) {
                    for (size_t p = 0; p < BUCKET_SIZE + W_NUM + 1; p++) {
                        C->cloud_t_table->final_t_table[k]->tx_coef[p] = C->cloud_t_table->User_A_t_table[i]->tx_coef[p] + C->cloud_t_table->User_B_t_table[j]->tx_coef[p];
                    }
                }
            }
        }
    }

    /*-----------------------云平台计算RIE随机编码------------------------------*/

    /*-----------------------用户B接收用户A和云平台的输出------------------------------*/

    for (size_t i = 0; i < TABLE_SIZE; i++) {
        for (size_t j = 0; j < BUCKET_SIZE + W_NUM + 1; j++) {
            B->my_rie_table->my_rie_table[i]->rie_x_coef[j] =
                    C->cloud_t_table->final_t_table[i]->tx_coef[j] + A->qtable->final_qtable[i]->qx_coef[j];
        }
    }

    /*-----------------------用户B接收用户A和云平台的输出------------------------------*/
}


void check_RIE(User *u, int s) //检查是否存在共同存有的元素
{
    int hash = Hash(s); //先找这个元素应该在哪个桶里
    long long result = 0; //初始化一个结果，先将其置为0
    for (size_t i = 0; i < BUCKET_SIZE + W_NUM + 1; i++) {
        long long temp = power(s, i);
        result += u->my_rie_table->my_rie_table[hash]->rie_x_coef[i] * temp;
    }
    if (result == 0) {
        printf("该元素存在。");
    } 
    else {
        printf("该元素不存在。");
    }
}

/*-------------------------------------------操作实现函数部分------------------------------------------*/

int main() {
    
/*--------------初始化操作------------------*/    
    srand(time(NULL));
    User *User_A = malloc(sizeof(User));
    User *User_B = malloc(sizeof(User));
    CloudServer *Cloud_C = malloc(sizeof(CloudServer));

    if (User_A == NULL || User_B == NULL || Cloud_C == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        return 1;
    }

    initialize_user(User_A);
    initialize_user(User_B);
    initialize_cloud(Cloud_C);

    strcpy(User_A->name, "UserA");
    strcpy(User_B->name, "UserB");
    User_A->User_symbol = 1;
    User_B->User_symbol = 2;

    generate(User_A, Cloud_C);
    generate(User_B, Cloud_C);
/*--------------初始化操作------------------*/

/*------------A中进行操作------------*/
    
    insert(User_A, Cloud_C, 6);
    delete(User_A, Cloud_C, 6);
    insert(User_A, Cloud_C, 7);
    insert(User_A, Cloud_C, 9);
    insert(User_A, Cloud_C, 15);

/*------------A中进行操作------------*/

/*------------B中进行操作------------*/
    
    insert(User_B, Cloud_C, 7);
    insert(User_B, Cloud_C, 9);
    insert(User_B, Cloud_C, 15);

/*------------A中进行操作------------*/
    

    RIE(User_A, User_B, Cloud_C); //进行隐私求交操作
    check_RIE(User_B, 15);  //用户B检查是否存在元素


    free_user(User_A);
    free_user(User_B);
    free_cloud(Cloud_C);

    free(User_A);
    free(User_B);
    free(Cloud_C);

    return 0;

    //防碰撞哈希让数据均匀分布到哈希表里，球入箱问题解决table长度，w的次数（胡老师会算一下），拉格朗日插值法，每一行的求交（O(1)性能）
    //可解决的问题： 批量上传和删除
}
